package org.zhang.core.config;

import java.io.InputStream;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

public class ProfilingFilter {
    private static Set<String> assignPackagePrefix = new HashSet<>();
    private static Set<String> exceptPackagePrefix = new HashSet<>();
    private static Set<String> exceptMethods = new HashSet<>();
    private static AtomicInteger number = new AtomicInteger(0);

    static {
        try {
            Properties properties = loadProperties("application.properties");
            assignPackagePrefix.addAll(Arrays.asList(properties.getProperty("profiling.filter.assign-package-prefix").split(",")));
            exceptPackagePrefix.addAll(Arrays.asList(properties.getProperty("profiling.filter.except-package-prefix").split(",")));
            exceptMethods.addAll(Arrays.asList(properties.getProperty("profiling.filter.except-methods").split(",")));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Properties loadProperties(String configFile) {
        Properties properties = new Properties();
        try (InputStream input = ProfilingFilter.class.getClassLoader().getResourceAsStream(configFile)) {
            if (input != null) {
                properties.load(input);
            } else {
                System.err.println("Unable to find " + configFile);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return properties;
    }

    /**
     * 需要插桩的类
     *
     * @param className
     * @return
     */
    public static boolean isNeedInject(String className) {
        if (null == className) return false;
        boolean flag = false;

        for (String prefix : assignPackagePrefix) {
            if (matcher(prefix, className) && !className.contains("$")) {
                flag = true;
                break;
            }
        }
        for (String prefix : exceptPackagePrefix) {
            if (matcher(prefix, className)) {
                flag = false;
                break;
            }
        }
        if (flag) {
            //查看插桩了哪些类
            System.out.println("className:" + className);
        }
        return flag;
    }

    public static boolean matcher(String pattern, String className) {
        PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
        Path path = Paths.get(className);
        return matcher.matches(path);
    }

    /**
     * 不需要插桩的类
     *
     * @param className
     * @return
     */
    public static boolean isNotNeedInject(String className) {
        return !isNeedInject(className);
    }

    /**
     * 需要插桩的方法
     *
     * @param methodName
     * @return
     */
    public static boolean isNeedInjectMethod(String methodName) {
        if (null == methodName || exceptMethods.contains(methodName)) {
            return false;
        }
        int currentNumber = number.incrementAndGet();
        //查看插桩了哪些方法
        System.out.println("插桩第" + currentNumber + "个方法:" + methodName);
        return true;
    }

    /**
     * 不需要插桩的方法
     *
     * @param methodName
     * @return
     */
    public static boolean isNotNeedInjectMethod(String methodName) {
        return !isNeedInjectMethod(methodName);
    }
}
